﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Pout_Porri.Objects.Interface;
using Pout_Porri.Objects.Bosses;
using Pout_Porri.Utils;
using Pout_Porri.Levels;
using System.IO;

namespace Pout_Porri.Objects
{

    public enum MarioStates
    {
        walking,
        running,
        runningtopspeed,
        crouching,
        stand,
        jumping,
        falling,
        lookingup,
        climbing,
        climbingstop,
        dying,

    }

    class Mario : PhysicsGameEntity, IGameEntity, ICollisionBoundaries
    {
        protected MarioStates currentState;

        private int maxJumps = 2;

        protected int MaxJumps
        {
            get { return maxJumps; }
            set { maxJumps = value; }
        }

        private int contJumps = 0;

        private float jumpHeight = 15;

        protected float JumpHeight
        {
            get { return jumpHeight; }
            set { jumpHeight = value; }
        }

        private Boolean isGrown;
        public Boolean IsGrown
        {
            get { return isGrown; }
            set { isGrown = value; }
        }

        private bool isBoundaryLeft;
        public bool IsBoundaryLeft
        {
            get
            {
                return isBoundaryLeft;
                //throw new NotImplementedException();
            }
            set
            {
                isBoundaryLeft = value;
                //throw new NotImplementedException();
            }
        }

        private bool isBoundaryRight;
        public bool IsBoundaryRight
        {
            get
            {
                return isBoundaryRight;
                //throw new NotImplementedException();
            }
            set
            {
                isBoundaryRight = value;
                //throw new NotImplementedException();
            }
        }

        private bool isBoundaryTop;
        public bool IsBoundaryTop
        {
            get
            {
                return isBoundaryTop;
                //throw new NotImplementedException();
            }
            set
            {
                isBoundaryTop = value;
                //throw new NotImplementedException();
            }
        }


        private double elapsedTime;
        private bool isRopeGrabbed = false;
        private Rope rope;
        private Turtle turtle;


        private MagicLake magicLake;

        public Mario(Texture2D image, Vector2 position, Vector2 velocity)
            : base(image, position, velocity, true)
        {
            this.texture = image;
            this.spriteTexture = new Texture2D(Game1.graphics.GraphicsDevice, 84, 84);
            DefaultVelocityX = velocity.X;
            MaxJumps = 1;
            this.currentState = MarioStates.stand;
            this.configAnimations();

        }


        #region "Configuração de animações"
        public void configAnimations()
        {

            Animation marioStand = new Animation("stand", new Vector2(84, 84), 100, 3, 0, 1, Axis.X);

            Animation marioWalking = new Animation("walking", new Vector2(84, 84), 150, 0, 0, 4, Axis.X);

            Animation marioRunning = new Animation("running", new Vector2(84, 84), 80, 0, 0, 4, Axis.X);

            Animation marioRunningTopSpeed = new Animation("runningtopspeed", new Vector2(84, 84), 80, 0, 0, 4, Axis.X);

            Animation marioJumping = new Animation("jumping", new Vector2(84, 84), 250, 4, 0, 1, Axis.X);

            Animation marioFalling = new Animation("falling", new Vector2(84, 84), 250, 5, 0, 1, Axis.X);

            Animation marioCrouching = new Animation("crouching", new Vector2(84, 84), 250, 6, 0, 1, Axis.X);

            Animation marioLookingup = new Animation("lookingup", new Vector2(84, 84), 250, 7, 0, 1, Axis.X);

            Animation marioClimbing = new Animation("climbing", new Vector2(84, 84), 250, 10, 0, 12, Axis.X);

            Animation marioClimbingStop = new Animation("climbingstop", new Vector2(84, 84), 150, 11, 0, 1, Axis.X);

            Animation marioDying = new Animation("dying", new Vector2(84, 84), 250, 8, 0, 2, Axis.X);


            Animation marioStand2 = new Animation("stand2", new Vector2(84, 84), 100, 5, 1, 1, Axis.X);

            Animation marioWalking2 = new Animation("walking2", new Vector2(84, 84), 110, 0, 1, 6, Axis.X);

            Animation marioRunning2 = new Animation("running2", new Vector2(84, 84), 80, 0, 1, 6, Axis.X);

            Animation marioRunningTopSpeed2 = new Animation("runningtopspeed2", new Vector2(84, 84), 80, 0, 2, 3, Axis.X);

            Animation marioJumping2 = new Animation("jumping2", new Vector2(84, 84), 250, 6, 1, 1, Axis.X);

            Animation marioFalling2 = new Animation("falling2", new Vector2(84, 84), 250, 7, 1, 1, Axis.X);

            Animation marioCrouching2 = new Animation("crouching2", new Vector2(84, 84), 250, 8, 1, 1, Axis.X);

            Animation marioLookingup2 = new Animation("lookingup2", new Vector2(84, 84), 250, 9, 1, 1, Axis.X);

            Animation marioClimbing2 = new Animation("climbing2", new Vector2(84, 84), 150, 10, 1, 12, Axis.X);

            Animation marioClimbingStop2 = new Animation("climbingstop2", new Vector2(84, 84), 250, 11, 1, 1, Axis.X);

            Animation marioDying2 = new Animation("dying2", new Vector2(84, 84), 250, 8, 0, 2, Axis.X);

            this.addAnimation(marioStand);
            this.addAnimation(marioWalking);
            this.addAnimation(marioRunning);
            this.addAnimation(marioRunningTopSpeed);
            this.addAnimation(marioJumping);
            this.addAnimation(marioFalling);
            this.addAnimation(marioCrouching);
            this.addAnimation(marioLookingup);
            this.addAnimation(marioClimbing);
            this.addAnimation(marioClimbingStop);
            this.addAnimation(marioDying);


            this.addAnimation(marioStand2);
            this.addAnimation(marioWalking2);
            this.addAnimation(marioRunning2);
            this.addAnimation(marioRunningTopSpeed2);
            this.addAnimation(marioJumping2);
            this.addAnimation(marioFalling2);
            this.addAnimation(marioCrouching2);
            this.addAnimation(marioLookingup2);
            this.addAnimation(marioClimbing2);
            this.addAnimation(marioClimbingStop2);
            this.addAnimation(marioDying2);

            this.setCurrentAnimation("stand");
        }
        #endregion

        #region "Input do usuário"
        public void handleInput()
        {
            MarioStates pState = currentState;

            direction.X = 0;
            if (IsGrounded())
                pState = MarioStates.stand;

            if (currentState != MarioStates.jumping && currentState != MarioStates.falling &&
                !isClimbingUp && !isClimbingDown)
                pState = MarioStates.stand;

            if (Game1.keyboardState.IsKeyDown(Keys.Right) && (!isClimbingDown || !isClimbingUp))
            {
                if (currentState != MarioStates.crouching && currentState != MarioStates.lookingup)
                {
                    this.deFlipHorizontally();
                    direction.X = 1;
                    if (currentState != MarioStates.jumping && currentState != MarioStates.falling)
                    {
                        pState = MarioStates.walking;
                    }
                }
            }

            else if (Game1.keyboardState.IsKeyDown(Keys.Left) && (!isClimbingDown || !isClimbingUp))
            {
                if (currentState != MarioStates.crouching && currentState != MarioStates.lookingup)
                {
                    this.flipHorizontally();
                    direction.X = -1;
                    if (currentState != MarioStates.jumping && currentState != MarioStates.falling)
                    {
                        pState = MarioStates.walking;
                    }
                }
            }

            if (Game1.keyboardState.IsKeyDown(Keys.Space) && !Game1.previusKeyboardState.IsKeyDown(Keys.Space))
            {
                if (contJumps < maxJumps)
                {
                    contJumps++;
                    this.Velocity = new Vector2(this.Velocity.X, -jumpHeight);
                    this.setGrounded(false);
                    pState = MarioStates.jumping;
                }
            }

            if (this.direction.Y != 0 && this.velocity.Y > 0 && !IsGrounded())
            {
                pState = MarioStates.falling;

            }

            if (Game1.keyboardState.IsKeyDown(Keys.LeftShift) && this.direction.X != 0)
            {
                isRunning = true;
                if (this.direction.Y == 0 && this.velocity.X < this.MaxVelocityX)
                    pState = MarioStates.running;
                else if (this.direction.Y == 0 && this.velocity.X >= this.MaxVelocityX && isGrown == true)
                    pState = MarioStates.runningtopspeed;
                else if (this.direction.Y == 0)
                    pState = MarioStates.running;

            }

            if (Game1.keyboardState.IsKeyUp(Keys.LeftShift))
            {
                isRunning = false;
            }

            if (isClimbingDown || isClimbingUp)
            {
                //if (Game1.keyboardState.IsKeyUp(Keys.Down) || Game1.keyboardState.IsKeyUp(Keys.Up))
                this.zOrder = 0.9f;
                pState = MarioStates.climbingstop;
            }
            else
            {
                this.zOrder = 0;
            }

            if (Game1.keyboardState.IsKeyDown(Keys.Down) && currentState != MarioStates.jumping
                    && currentState != MarioStates.falling && currentState != MarioStates.walking
                    && currentState != MarioStates.running)
            {
                if (!isClimbingDown)
                {
                    pState = MarioStates.crouching;
                    setGrounded(true);
                }

                else if (isClimbingDown)
                {
                    pState = MarioStates.climbing;
                    direction.Y = 1;
                    position.Y += direction.Y;
                }
            }



            if (Game1.keyboardState.IsKeyDown(Keys.Up) && currentState != MarioStates.jumping
                && currentState != MarioStates.falling && currentState != MarioStates.walking
                && currentState != MarioStates.running)
            {
                if (!isClimbingUp)
                {
                    pState = MarioStates.lookingup;
                    setGrounded(true);
                }
                else if (isClimbingUp)
                {
                    pState = MarioStates.climbing;
                    direction.Y = -1;
                    position.Y += direction.Y;

                }
            }



            if (pState != currentState)
            {
                currentState = pState;
            }
        }
        #endregion

        public override void setGrounded(bool b)
        {
            base.setGrounded(b);
            if (b == true)
            {
                contJumps = 0; // reset the jumps
            }
        }

        public override void update(GameTime gameTime)
        {
            handleInput();

            currentAnimationRect = this.AnimationRect(this.getCurrentAnimation());

            #region "collisions"

            if (World.isCollisionEntity)
            {
                if (World.entityCollided is Flower)
                {
                    if (this.IsGrown)
                        IsGrown = false;
                }



                if (World.entityCollided is Helmet)
                {
                    if (this.IsGrown)
                        IsGrown = false;
                }

                if (World.entityCollided is HedgeHog)
                {
                    if (this.IsGrown)
                        IsGrown = false;
                }

                //if (World.entityCollided is BigGhost)
                //{
                //    if (this.IsGrown)
                //        IsGrown = false;
                //}

                if (World.entityCollided is Wall)
                {

                    if (this.position.X <= World.entityCollided.position.X)
                    {
                        position.X -= 2;
                        isRunning = false;

                    }
                    else if (this.position.X >= World.entityCollided.position.X)
                    {
                        currentState = MarioStates.dying;

                    }
                }

                if (World.entityCollided is Rope)
                {
                    isRopeGrabbed = true;
                    rope = (Rope)World.entityCollided;
                }

                if (World.entityCollided is Turtle)
                {
                    if (gameTime.TotalGameTime.TotalMilliseconds > elapsedTime + 10)
                    {
                        elapsedTime = gameTime.TotalGameTime.TotalMilliseconds;

                        //this.direction.Y = -1;
                        this.velocity.Y = 1;
                        this.position.Y -= 1;
                        Game1.window.Title = "" + this.cima + " " + this.position.Y;

                        this.setGrounded(true);

                    }
                }

                if (World.entityCollided is MagicLake)
                {
                    magicLake = (MagicLake)World.entityCollided;
                }


            }

            collisionBoundaries();

            this.applyMovement(gameTime);

            if (!this.collisionHole() && !this.collisionLadder())
                checkMatrixCollisionInY();

            #endregion

            #region "animation"

            if (currentState == MarioStates.stand)
            {
                if (!isGrown)
                    this.setCurrentAnimation("stand");
                else
                    this.setCurrentAnimation("stand2");
                //Game1.window.Title = "stand";
                //this.playCurrentAnimation("stand",gameTime);
            }
            else if (currentState == MarioStates.walking)
            {
                //Game1.window.Title = "walking";
                if (!isGrown)
                    this.setCurrentAnimation("walking");
                else
                    this.setCurrentAnimation("walking2");
                //this.playCurrentAnimation("running", gameTime);
            }
            else if (currentState == MarioStates.running)
            {
                //Game1.window.Title = "running";
                if (!isGrown)
                    this.setCurrentAnimation("running");
                else
                    this.setCurrentAnimation("running2");
                //this.playCurrentAnimation("running", gameTime);
            }
            else if (currentState == MarioStates.runningtopspeed)
            {
                Game1.window.Title = "runningtopspeed";
                if (!isGrown)
                    this.setCurrentAnimation("runningtopspeed");
                else
                    this.setCurrentAnimation("runningtopspeed2");
                //this.playCurrentAnimation("running", gameTime);
            }
            else if (currentState == MarioStates.jumping)
            {
                //Game1.window.Title = "jumping";
                if (!isGrown)
                    this.setCurrentAnimation("jumping");
                else
                    this.setCurrentAnimation("jumping2");
            }
            else if (currentState == MarioStates.falling)
            {
                //Game1.window.Title = "falling";
                if (!isGrown)
                    this.setCurrentAnimation("falling");
                else
                    this.setCurrentAnimation("falling2");
            }
            else if (currentState == MarioStates.crouching)
            {
                //Game1.window.Title = "crouching";
                if (!isGrown)
                    this.setCurrentAnimation("crouching");
                else
                    this.setCurrentAnimation("crouching2");
            }
            else if (currentState == MarioStates.lookingup)
            {
                //Game1.window.Title = "lookingup";
                if (!isGrown)
                    this.setCurrentAnimation("lookingup");
                else
                    this.setCurrentAnimation("lookingup2");
            }
            else if (currentState == MarioStates.climbing)
            {
                //Game1.window.Title = "climbing";
                if (!isGrown)
                    this.setCurrentAnimation("climbing");
                else
                    this.setCurrentAnimation("climbing2");
            }
            else if (currentState == MarioStates.climbingstop)
            {
                //Game1.window.Title = "climbing";
                if (!isGrown)
                    this.setCurrentAnimation("climbingstop");
                else
                    this.setCurrentAnimation("climbingstop2");
            }
            else if (currentState == MarioStates.dying)
            {
                Game1.window.Title = "dying";
                if (!isGrown)
                    this.setCurrentAnimation("dying");
                else
                    this.setCurrentAnimation("dying2");
            }

            #endregion

            base.update(gameTime);
        }

        public void collisionBoundaries()
        {
            if (this.position.X < Game1.graphics.GraphicsDevice.Viewport.Bounds.Left - 20)
            {
                this.position.X = Game1.graphics.GraphicsDevice.Viewport.Bounds.Left - 20;
                isBoundaryLeft = true;
            }
            else
            {
                isBoundaryLeft = false;
            }

            if (this.position.X > 745)
            {
                isBoundaryRight = true;
            }
            else
            {
                isBoundaryRight = false;
            }

        }

        public bool collisionLadder()
        {
            Rectangle rectTestCollision = CollisionRect;
            Point tileCenter = new Point(rectTestCollision.Center.X / GameConfig.TILE_SIZE, rectTestCollision.Bottom / GameConfig.TILE_SIZE);
            TileType tileTypeCenter = MyLevel.Tileset.getTileType(MyLevel.CollisionMatrix[tileCenter.Y, tileCenter.X]);

            //Game1.window.Title = "" + tileTypeCenter + " " +  this.position.X + " " + (tileCenter.X * 32 - 32);


            if (tileTypeCenter == TileType.FIRST_STEP_LADDER || tileTypeCenter == TileType.LADDER)
            {

                if (Game1.keyboardState.IsKeyDown(Keys.Up) &&
                    tileTypeCenter != TileType.HOLE &&
                    this.position.X > (tileCenter.X * GameConfig.TILE_SIZE - GameConfig.TILE_SIZE) &&
                    this.position.X < (tileCenter.X * GameConfig.TILE_SIZE - GameConfig.TILE_SIZE + 16))
                {
                    //this.zOrder = 1.1f;
                    this.position.X = tileCenter.X * GameConfig.TILE_SIZE - GameConfig.TILE_SIZE + 8;
                    isClimbingDown = false;
                    isClimbingUp = true;
                    this.currentState = MarioStates.climbing;
                    return true;
                }
                else if (Game1.keyboardState.IsKeyDown(Keys.Down) && tileTypeCenter != TileType.FIRST_STEP_LADDER)
                {
                    this.position.X = tileCenter.X * GameConfig.TILE_SIZE - GameConfig.TILE_SIZE + 8;
                    this.currentState = MarioStates.climbing;
                    isClimbingUp = false;
                    isClimbingDown = true;
                    return true;
                }
                else if (Game1.keyboardState.IsKeyDown(Keys.Down) && tileTypeCenter == TileType.FIRST_STEP_LADDER)
                {
                    if (this.currentState == MarioStates.climbing || this.currentState == MarioStates.climbingstop)
                        this.currentState = MarioStates.stand;
                    else
                        this.currentState = MarioStates.crouching;

                    isClimbingUp = false;
                    isClimbingDown = false;
                    return false;
                }


            }
            return false;
        }

        public bool collisionHole()
        {
            Rectangle rectTestCollision = CollisionRect;
            Point tileCenter = new Point(rectTestCollision.Center.X / GameConfig.TILE_SIZE, rectTestCollision.Bottom / GameConfig.TILE_SIZE);
            TileType tileTypeCenter = MyLevel.Tileset.getTileType(MyLevel.CollisionMatrix[tileCenter.Y, tileCenter.X]);



            if (tileTypeCenter == TileType.HOLE && this.position.X > (tileCenter.X * GameConfig.TILE_SIZE - GameConfig.TILE_SIZE))
            {
                if (isClimbingUp)
                {
                    //Game1.window.Title = "" + this.position.Y + " " + this.position.X + " " + (tileCenter.X * 32 - 32);
                    this.position.Y -= 30;
                    isClimbingUp = false;

                    this.position.X += 25;
                    this.setGrounded(false);
                    this.currentState = MarioStates.jumping;
                    return false;

                }
                this.currentState = MarioStates.falling;
                isFallingHole = true;
                this.velocity.Y = 10;
                return true;
            }
            isFallingHole = false;
            return false;
        }
    }
}